package com.nulldev.util.java;

import java.util.ArrayList;
import java.util.List;

import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;

public class Variables {

    public static boolean isEmpty(final String string) {
        return string == null || string.length() == 0;
    }

    public static boolean isNotEmpty(final String string) {
        return string != null && string.length() != 0;
    }

    public static void validateNotNull(final Object object, final String message) {
        if (object == null) {
            throw new IllegalArgumentException(message);
        }
    }

    public static boolean notNull(final Object object) {
    	return (object != null);
    }
    
    public static <T> T notNullI(final T object) {
    	return (object != null ? object : null);
    }
    
    public static <T> T notNullI(final T object, final String text) {
    	if (object != null) {
    		return object;
    	}
    	throw new RuntimeException(text);
    }

    public static boolean isNull(final Object object) {
    	return (object == null);
    }

    public static void validateNotEmpty(final String string, final String message) {
        if (isEmpty(string)) {
            throw new IllegalArgumentException(message);
        }
    }

    public static void validateIsTrue(final boolean expression, final String message) {
        if (!expression) {
            throw new IllegalArgumentException(message);
        }
    }

    public static String[] split(final String string) {
        return split(string, null);
    }

    public static String[] split(final String string, final String separators) {
        if (string == null) {
            return new String[0];
        }
        final int length = string.length();
        if (length == 0) {
            return new String[0];
        }
        final List results = new ArrayList();
        int i = 0;
        int start = 0;
        boolean tokenInProgress = false;
        if (separators == null) {
            while (i < length) {
                if (Character.isWhitespace(string.charAt(i))) {
                    if (tokenInProgress) {
                        results.add(string.substring(start, i));
                        tokenInProgress = false;
                    }
                    start = ++i;
                }
                else {
                    tokenInProgress = true;
                    ++i;
                }
            }
        }
        else if (separators.length() == 1) {
            final char separator = separators.charAt(0);
            while (i < length) {
                if (string.charAt(i) == separator) {
                    if (tokenInProgress) {
                        results.add(string.substring(start, i));
                        tokenInProgress = false;
                    }
                    start = ++i;
                }
                else {
                    tokenInProgress = true;
                    ++i;
                }
            }
        }
        else {
            while (i < length) {
                if (separators.indexOf(string.charAt(i)) >= 0) {
                    if (tokenInProgress) {
                        results.add(string.substring(start, i));
                        tokenInProgress = false;
                    }
                    start = ++i;
                }
                else {
                    tokenInProgress = true;
                    ++i;
                }
            }
        }
        if (tokenInProgress) {
            results.add(string.substring(start, i));
        }
        return (String[]) results.toArray(new String[results.size()]);
    }

    public static byte[] appendArrays(final byte[] firstArray, final byte[] secondArray) {
        validateNotNull(firstArray, "Appended array cannot be null");
        validateNotNull(secondArray, "Appended array cannot be null");
        final byte[] result = new byte[firstArray.length + secondArray.length];
        System.arraycopy(firstArray, 0, result, 0, firstArray.length);
        System.arraycopy(secondArray, 0, result, firstArray.length, secondArray.length);
        return result;
    }

    public static <T> var<T> createVar(final T obj){
    	return new var<T>(obj);
    }

	public static String isTrue(final boolean variable, final String string) {
		if (variable) {
			return string;
		}else {
			return "N/A";
		}
	}
	
	public static void isTrue(final boolean variable) {
		if (!variable) {
			throw new RuntimeException("variable was false!");
		}
	}

	private static final Logger log = LoggerFactory.getLogger();
	public static void notNull(byte[] data, final String string) {
		if (!notNull(data)) {
			throw new RuntimeException(string);
		}
	}

	public static void checkNotNull(final Object object) {
		if (!notNull(object)) {
			throw new RuntimeException("object == null!");
		}
	}
	
	public static void checkNotNull(final Object object, final String text) {
		if (!notNull(object)) {
			throw new RuntimeException(text);
		}
	}

    public static void checkState(final boolean expression) {
        if (!expression) {
            throw new IllegalStateException();
        }
    }

	public static int length(final String message) {
		if (message == null) {
			return 0;
		}
		return message.length();
	}
	
	private static final String DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE =
	        "The value %s is not in the specified inclusive range of %s to %s";

	public static <T> void inclusiveBetween(T start, T end, Comparable<T> value) {
        if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {
            throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
        }
    }
}
